/*
 * Copyright (c) 2010-2011, Monash e-Research Centre
 * (Monash University, Australia)
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 	* Redistributions of source code must retain the above copyright
 * 	  notice, this list of conditions and the following disclaimer.
 * 	* Redistributions in binary form must reproduce the above copyright
 * 	  notice, this list of conditions and the following disclaimer in the
 * 	  documentation and/or other materials provided with the distribution.
 * 	* Neither the name of the Monash University nor the names of its
 * 	  contributors may be used to endorse or promote products derived from
 * 	  this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package edu.monash.merc.struts2.multipart;

import java.text.NumberFormat;

import org.apache.commons.fileupload.ProgressListener;
import org.apache.log4j.Logger;

/**
 * This class is used to monitor the upload of a file from web page to the server
 */
public class ProgressMonitor implements ProgressListener {

    public static final String SESSION_PROGRESS_MONITOR = "merc.session.ProgressMonitor";

    private static final Logger logger = Logger.getLogger(ProgressMonitor.class);

    private static final NumberFormat fmt = NumberFormat.getInstance();

    // Previous Values
    private long previousBytesRead;

    private int bytesReadNotChangedCount;

    // Current Values
    private long bytesRead;

    private long bytesLength;

    private boolean aborted = false;

    private String fileName = "na";

    static {
        fmt.setMaximumFractionDigits(0);
    }

    /**
     * Creates a new instance of ProgressMonitor
     */
    public ProgressMonitor() {
        if (logger.isDebugEnabled()) {
            logger.debug("Creating Progress Monitor");
        }
    }

    /**
     * This is called by the notifier
     */
    @Override
    public void update(long pBytesRead, long pContentLength, int pItems) {
        bytesRead = pBytesRead;
        bytesLength = pContentLength;
    }

    /**
     * This looks at the previousBytesRead value which only will update when the file is being uploaded and it compares
     * it against the current bytes read value passed in as a param. If they are the same more the 3 times, we assume
     * the connection is broken and abort the upload.
     * <p/>
     * This is another safety measure to reset the upload form
     *
     * @return true if the file is still uploading, or false if it has failed
     */
    public boolean isStillProcessing() {
        if (logger.isDebugEnabled()) {
            logger.debug("BytesnotReadChangedCount is: " + bytesReadNotChangedCount);
        }
        if (bytesReadNotChangedCount > 3) {
            // Abort processing
            return false;
        } else {
            return true;
        }
    }

    /**
     * This returns the percentage complete
     */
    public String percentComplete() {
        double percent = ((double) bytesRead / (double) bytesLength);
        percent *= 100;
        return fmt.format(percent);
    }

    public long getBytesRead() {
        if (previousBytesRead == bytesRead) {
            bytesReadNotChangedCount++;
        } else {
            bytesReadNotChangedCount = 0;
            previousBytesRead = bytesRead;
        }
        return bytesRead;
    }

    public long getBytesLength() {
        return bytesLength;
    }

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public void abort() {
        this.aborted = true;
    }

    public boolean isAborted() {
        return this.aborted;
    }

    public void setPreviousBytesRead(long previousBytesRead) {
        this.previousBytesRead = previousBytesRead;
    }

}
